const fs = require('fs-extra');
const chalk = require('chalk');
const { exit, cwd } = require('process');
const { execSync } = require('child_process');
const inquirer = require('inquirer');
const download = require('download-git-repo');
const ora = require('ora');
import { exec } from 'shelljs';
import config from './config';
import { Choice, RepoInfo } from './types';
import { log } from './util/helper';
// 检查文件夹名称是否重复 => 拉取模板 => 更新 package.json 信息 =>  安装依赖
class CreatorClass {
  projectName: string;
  targetDir: string;
  constructor(projectName: string, targetDir: string) {
    this.projectName = projectName;
    this.targetDir = targetDir;
    this.init();
  }
  async init() {
    await this.checkTargetExist();
    // 选择模板
    const templateName = await this.checkTemplate();
    this.create(templateName);
  }
  async create(templateName: string) {
    // 克隆
    const address = config[templateName];
    await this.cloneRepo(this.projectName, address);
    // 检查是否安装git
    const shouldInitGit = this.shouldInitGit();
    if (shouldInitGit) {
      log.info(`🗃 初始化 Git 仓库...`);
      await execSync(`cd ${this.projectName} && git init`);
    } else {
      return log.error('请先手动安装git');
    }
    // 更改package.json的基础信息
    const repoInfo = await this.getRepoInfo();
    this.updatePackageInfo(this.projectName, repoInfo);
    // 安装依赖
    this.installPkg();
  }
  // 克隆模板到本地
  cloneRepo(targetDir: string, address: string) {
    const spinner = ora();
    spinner.start('正在拉取模板...');
    return new Promise((resolve, reject) => {
      download(`direct:${address}`, cwd() + `/${targetDir}`, { clone: true }, (err: any) => {
        if (err) {
          spinner.fail(chalk.red('模板拉取失败'));
          spinner.stop();
          reject();
          console.log('2023-03-16 19:58:10', err);
          return;
        }
        spinner.succeed(chalk.green('模板下载成功'));
        resolve(true);
      });
    });
  }
  // 判断是否可以初始化 git 仓库：系统安装了 git 且目录下未初始化过，则初始化
  shouldInitGit() {
    try {
      // 执行 git --version 命令并获取输出结果
      const result = execSync('git --version');
      console.log('Git 已经安装', result.toString());
      return true;
    } catch (error) {
      try {
        // 执行 brew install git 命令
        execSync('brew install git');
        this.shouldInitGit();
        return true;
      } catch (error) {
        return false;
        console.log('安装 Git 失败', error);
      }
      console.log('Git 未安装', error);
      return false;
    }
  }
  // 获取模板基础信息
  getRepoInfo = (): Promise<RepoInfo> => {
    return inquirer.prompt([
      {
        type: 'input',
        name: 'description',
        message: '请输入描述'
      },
      {
        type: 'input',
        name: 'author',
        message: '请输入作者'
      }
    ]);
  };
  // 更新 package.json 信息
  updatePackageInfo(target: string, repoInfo: RepoInfo) {
    const pkgJson = fs.readJsonSync(cwd() + `/${target}/package.json`);

    fs.writeFileSync(
      cwd() + `/${target}/package.json`,
      JSON.stringify(Object.assign(pkgJson, repoInfo, { name: target }), null, 2)
    );
  }

  async runExec(command: string) {
    return new Promise((resolve, reject) => {
      exec(command, (err: any) => {
        if (!err) return resolve(true);
        reject(err);
      });
    });
  }

  // 安装依赖
  async installPkg() {
    const spinner = ora();
    spinner.start('安装依赖中...');
    try {
      await this.runExec(`cd ${this.projectName} && npm i`);
      spinner.succeed(chalk.green('依赖安装完成🎉'));
      log.success(`  cd ${this.projectName} \n  npm run dev`);
    } catch (err) {
      spinner.fail(chalk.red('依赖安装失败'));
      spinner.stop();
    }
  }

  // 用户交互选择处理
  async handleChoice(projectName: string) {
    const { checkExist } = await inquirer.prompt({
      type: 'list',
      name: 'checkExist',
      message: `\\文件夹 ${projectName} 已存在`,
      choices: [Choice.rename, Choice.cover, Choice.cancel]
    });
    if (checkExist === Choice.rename) {
      // 重新输入
      const { inputNewName } = await inquirer.prompt({
        type: 'input',
        name: 'inputNewName',
        message: '请输入新的项目名称: '
      });
      if (inputNewName && inputNewName !== projectName) {
        this.projectName = inputNewName;
        return inputNewName;
      }
      const res: any = await this.handleChoice(projectName);
      if (res) return res;
    } else if (checkExist == Choice.cover) {
      // 覆盖,删除原来的文件
      fs.removeSync(projectName);
    } else {
      exit(1);
    }
  }
  // 检查文件夹名称是否重复
  async checkTargetExist() {
    const isExist = await fs.existsSync(this.targetDir);
    console.log('2023-03-16 09:10:37', isExist);
    if (isExist) {
      // 存在
      const res = await this.handleChoice(this.projectName);
      console.log('2023-03-16 09:01:26', res);
      return res;
    }
  }
  // 选择模板
  async checkTemplate() {
    const { name } = await inquirer.prompt({
      type: 'list',
      name: 'name',
      choices: ['vue2', 'vite-vue3', 'vite-react']
    });
    return name;
    console.log('2023-03-16 19:46:27', name);
  }
}

module.exports = CreatorClass;
